﻿using System;
using System.Collections.Concurrent;
using System.Net.Sockets;

namespace CS.Net
{
    /// <summary>
    /// 连接池
    /// <remarks>
    /// 使用SocketAsyncEventArgs对象集合作为连接池，为TCP连接提供支持。
    /// REF:http://msdn.microsoft.com/zh-cn/library/vstudio/system.net.sockets.socketasynceventargs(v=vs.100).aspx
    /// </remarks>
    /// </summary>
    public class ConnectionPool : IDisposable
    {
        private readonly ConcurrentStack<SocketAsyncEventArgs> _pool;
        private readonly int _maxBacklog;

        /// <summary>
        /// 使用128并发连接初始化
        /// </summary>
        public ConnectionPool()
            : this(128)
        {
        }

        /// <summary>
        /// 指定参数specified来初始化池
        /// </summary>
        /// <param name="backlog">并发连接数，最大值1024，默认128个</param>
        public ConnectionPool(int backlog)
        {
            _maxBacklog = backlog.ToInt(128, 2, 1024);
            _pool = new ConcurrentStack<SocketAsyncEventArgs>();
            for (int i = 0; i < _maxBacklog; i++)
            {
                _pool.Push(new SocketAsyncEventArgs());
            }
        }

        /// <summary>
        /// 数量
        /// </summary>
        public int Count
        {
            get { return _pool.Count; }
        }
        /// <summary>
        /// 最大容量
        /// <remarks>>Todo:超过该容器将阻塞通信</remarks>
        /// </summary>
        public int MaxCapacity
        {
            get { return _maxBacklog; }
        }

        /// <summary>
        /// 压入
        /// <remarks>不能压入空的对象</remarks>
        /// </summary>
        /// <param name="item"></param>
        public void Push(SocketAsyncEventArgs item)
        {
            if (item == null) return;//throw new ArgumentNullException("item", "Items added to a SocketAsyncEventArgsPool cannot be null");
            _pool.Push(item);
        }

        /// <summary>
        /// 弹出
        /// <remarks>必为实例，不为null(池空后创建新的实例)</remarks>
        /// </summary>
        /// <returns></returns>
        public SocketAsyncEventArgs Pop()
        {
            SocketAsyncEventArgs result;
            return _pool.TryPop(out result) ? result : new SocketAsyncEventArgs();
        }

        #region IDisposable 成员

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            SocketAsyncEventArgs result;
            while (_pool.TryPop(out result))
            {
                result.Dispose();
            }
            _pool.Clear();
        }

        #endregion

    }
}